#include "format.hh"
#include "../util/string_util.hh"
#include <sstream>
#include <vector>

namespace kratos {
namespace corelib {

Format::Format() {
}

Format::~Format() {
    for (auto& il : infoList_) {
        if (il.isText) {
            delete il.s;
        }
    }
    infoList_.clear();
}

bool Format::parse(const std::string & format) {
    std::vector<std::string> elems;
    StringUtil::splitBy(format, '%', elems);
    for (auto& elem : elems) {
        if (elem[0] != '%') {
            FormatElement e;
            e.isText = true;
            e.s = new std::string(elem);
            infoList_.emplace_back(e);
            continue;
        }
        auto c = elem[1];
        info i = info::none;
        switch(c) {
        case 'p':
            i = info::process;
            break;
        case 't':
            i = info::thread;
            break;
        case 'y':
            i = info::year;
            break;
        case 'm':
            i = info::month;
            break;
        case 'd':
            i = info::day;
            break;
        case 'H':
            i = info::hour;
            break;
        case 'M':
            i = info::minute;
            break;
        case 'S':
            i = info::second;
            break;
        case 's':
            i = info::million;
            break;
        case 'E':
            i = info::syserrno;
            break;
        case 'e':
            i = info::syserror;
            break;
        default:
            break;
        }        
        if (i == info::none) {
            FormatElement e;
            e.isText = true;
            e.s = new std::string(elem);
            infoList_.emplace_back(e);
        } else {
            FormatElement e;
            e.isText = false;
            e.i = i;
            infoList_.emplace_back(e);
            if (elem.size() > 2) {
                e.isText = true;
                e.s = new std::string(elem.begin() + 2, elem.end());
                infoList_.emplace_back(e);
            }
        }
    }
    return true;
}

void Format::format(LogImpl & log) {
    for (auto& il : infoList_) {
        if (il.isText) {
            log << *il.s;
        } else {
            log << il.i;
        }
    }
}

std::string Format::format() {
    LogImpl log(Level::verbose);
    format(log);
    return log.str();
}

}
}
